Skip to main content

classicube_sys\vectors\matrix/
mod.rs

1mod ops;
2
3use crate::{
4    Tan_Simple,
5    bindings::{
6        Matrix, Matrix_Mul, Matrix_RotateX, Matrix_RotateY, Matrix_RotateZ, Matrix_Scale,
7        Matrix_Translate, Vec2, Vec3, Vec4,
8    },
9    std_types::{c_double, c_float},
10};
11
12impl Matrix {
13    pub const IDENTITY: Self = Matrix_IdentityValue();
14
15    #[must_use]
16    pub const fn identity_value() -> Self {
17        Matrix_IdentityValue()
18    }
19
20    /// Returns a matrix representing a counter-clockwise rotation around x axis.
21    #[must_use]
22    pub fn rotate_x(angle: c_float) -> Self {
23        let mut result = Self::IDENTITY;
24        unsafe {
25            Matrix_RotateX(&raw mut result, angle);
26        }
27        result
28    }
29
30    /// Returns a matrix representing a counter-clockwise rotation around y axis.
31    #[must_use]
32    pub fn rotate_y(angle: c_float) -> Self {
33        let mut result = Self::IDENTITY;
34        unsafe {
35            Matrix_RotateY(&raw mut result, angle);
36        }
37        result
38    }
39
40    /// Returns a matrix representing a counter-clockwise rotation around z axis.
41    #[must_use]
42    pub fn rotate_z(angle: c_float) -> Self {
43        let mut result = Self::IDENTITY;
44        unsafe {
45            Matrix_RotateZ(&raw mut result, angle);
46        }
47        result
48    }
49
50    /// Returns a matrix representing a translation to the given coordinates.
51    #[must_use]
52    pub fn translate(x: c_float, y: c_float, z: c_float) -> Self {
53        let mut result = Self::IDENTITY;
54        unsafe {
55            Matrix_Translate(&raw mut result, x, y, z);
56        }
57        result
58    }
59
60    /// Returns a matrix representing a scaling by the given factors.
61    #[must_use]
62    pub fn scale(x: c_float, y: c_float, z: c_float) -> Self {
63        let mut result = Self::IDENTITY;
64        unsafe {
65            Matrix_Scale(&raw mut result, x, y, z);
66        }
67        result
68    }
69
70    #[must_use]
71    pub fn orthographic(
72        left: c_float,
73        right: c_float,
74        top: c_float,
75        bottom: c_float,
76        zNear: c_float,
77        zFar: c_float,
78    ) -> Self {
79        let mut result = Self::IDENTITY;
80        Matrix_Orthographic(&mut result, left, right, top, bottom, zNear, zFar);
81        result
82    }
83
84    #[must_use]
85    pub fn perspective_field_of_view(
86        fovy: c_float,
87        aspect: c_float,
88        z_near: c_float,
89        z_far: c_float,
90    ) -> Self {
91        let mut result = Self::IDENTITY;
92        Matrix_PerspectiveFieldOfView(&mut result, fovy, aspect, z_near, z_far);
93        result
94    }
95
96    #[must_use]
97    pub fn look_rot(pos: Vec3, rot: Vec2) -> Self {
98        let mut result = Self::IDENTITY;
99        Matrix_LookRot(&mut result, pos, rot);
100        result
101    }
102}
103
104#[must_use]
105pub const fn Matrix_IdentityValue() -> Matrix {
106    Matrix {
107        row1: Vec4 {
108            x: 1.0,
109            y: 0.0,
110            z: 0.0,
111            w: 0.0,
112        },
113        row2: Vec4 {
114            x: 0.0,
115            y: 1.0,
116            z: 0.0,
117            w: 0.0,
118        },
119        row3: Vec4 {
120            x: 0.0,
121            y: 0.0,
122            z: 1.0,
123            w: 0.0,
124        },
125        row4: Vec4 {
126            x: 0.0,
127            y: 0.0,
128            z: 0.0,
129            w: 1.0,
130        },
131    }
132}
133
134/// Identity matrix. (A * Identity = A)
135pub const Matrix_Identity: Matrix = Matrix_IdentityValue();
136
137pub fn Matrix_Orthographic(
138    result: &mut Matrix,
139    left: c_float,
140    right: c_float,
141    top: c_float,
142    bottom: c_float,
143    zNear: c_float,
144    zFar: c_float,
145) {
146    /* Transposed, source https://msdn.microsoft.com/en-us/library/dd373965(v=vs.85).aspx */
147    *result = Matrix_Identity;
148
149    result.row1.x = 2.0 / (right - left);
150    result.row2.y = 2.0 / (top - bottom);
151    result.row3.z = -2.0 / (zFar - zNear);
152
153    result.row4.x = -(right + left) / (right - left);
154    result.row4.y = -(top + bottom) / (top - bottom);
155    result.row4.z = -(zFar + zNear) / (zFar - zNear);
156}
157
158pub fn Matrix_PerspectiveFieldOfView(
159    result: &mut Matrix,
160    fovy: c_float,
161    aspect: c_float,
162    zNear: c_float,
163    zFar: c_float,
164) {
165    #[expect(
166        clippy::cast_possible_truncation,
167        reason = "fovy projection collapses back to f32"
168    )]
169    let c = zNear * Tan_Simple(0.5 * c_double::from(fovy)) as c_float;
170
171    /* Transposed, source https://msdn.microsoft.com/en-us/library/dd373537(v=vs.85).aspx */
172    /* For a FOV based perspective matrix, left/right/top/bottom are calculated as: */
173    /* left = -c * aspect, right = c * aspect, bottom = -c, top = c */
174    /* Calculations are simplified because of left/right and top/bottom symmetry */
175    *result = Matrix_Identity;
176    result.row4.w = 0.0;
177
178    result.row1.x = zNear / (c * aspect);
179    result.row2.y = zNear / c;
180    result.row4.z = -(2.0 * zFar * zNear) / (zFar - zNear);
181    result.row3.z = -(zFar + zNear) / (zFar - zNear);
182    result.row3.w = -1.0;
183}
184
185pub fn Matrix_LookRot(result: &mut Matrix, pos: Vec3, rot: Vec2) {
186    let mut rotX = Matrix_Identity;
187    let mut rotY = Matrix_Identity;
188    let mut trans = Matrix_Identity;
189
190    unsafe {
191        Matrix_RotateX(&raw mut rotX, rot.y);
192        Matrix_RotateY(&raw mut rotY, rot.x);
193        Matrix_Translate(&raw mut trans, -pos.x, -pos.y, -pos.z);
194
195        Matrix_Mul(result, &raw const rotY, &raw const rotX);
196        Matrix_Mul(result, &raw const trans, result);
197    }
198}